package com.lianqi.emcpframework.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

/**
 * @program emcp-framework
 * @ClassName ThreadLocalUtils
 * @description: ThreadLocal工具类，通过在ThreadLocal存储map信息,来实现在ThreadLocal中维护多个信息 <br>
 *               e.g.<code>
 * ThreadLocalUtils.put("key",value);<br>
 * ThreadLocalUtils.get("key");<br>
 * ThreadLocalUtils.remove("key");<br>
 * ThreadLocalUtils.getAndRemove("key");<br>
 * ThreadLocalUtils.get("key",()-&gt;defaultValue);<br>
 * ThreadLocalUtils.clear();<br>
 * </code>
 * @author: sky
 * @create: 2018/11/17 17:07
 */
public class ThreadLocalUtils {

    private static final ThreadLocal<Map<String, Object>> local = ThreadLocal.withInitial(HashMap::new);

    /**
     * 获取ThreadLocal中的所有对象
     * 
     * @return ThreadLocal中的所有值
     */
    public static Map<String, Object> getAll() {
        return local.get();
    }

    /**
     * 获取对象
     * 
     * @param key
     *            键值
     * @param <T>
     *            泛型值
     * @return 对象，不存在则返回null，如果类型与泛型不一致，可能抛出{@link ClassCastException}
     */
    public static <T> T get(String key) {
        return (T)local.get().get(key);
    }

    /**
     * 获取对象，指定一个当值不存在的提供者
     * 
     * @param key
     *            键值
     * @param supplier
     *            提供者
     * @param <T>
     * @return
     */
    public static <T> T get(String key, Supplier<T> supplier) {
        return (T)local.get().computeIfAbsent(key, k -> supplier.get());
    }

    /**
     * 查询并删除
     * 
     * @param key
     *            键值
     * @param <T>
     *            值类型
     * @return 对象，不存在则返回null
     */
    public static <T> T getAndRemove(String key) {
        try {
            return get(key);
        } finally {
            remove(key);
        }
    }

    /**
     * 在ThreadLocal中放入一个对象
     * 
     * @param key
     *            键值
     * @param value
     *            对象
     * @param <T>
     *            对象类型
     * @return 被放入的值
     */
    public static <T> T put(String key, T value) {
        local.get().put(key, value);
        return value;
    }

    /**
     * 删除对象
     * 
     * @param key
     *            对象的key
     */
    public static void remove(String key) {
        local.get().remove(key);
    }

    /**
     * 清空Threadlocal
     * 
     * @see Map#clear()
     */
    public static void clear() {
        local.remove();
    }

}
